package android.slc.box.core.controller;

import cn.hutool.core.lang.Validator;
import javafx.scene.control.TextFormatter;
import javafx.util.StringConverter;

import java.util.function.UnaryOperator;
import java.util.regex.Pattern;

/**
 * 一般的控制器
 *
 * @author slc
 * @date 2022/03/28 下午 5:58
 */
public class CustomTextFormatter extends TextFormatter<String> {

    public CustomTextFormatter(Pattern pattern, CheckResultListener checkResultListener) {
        super(new CheckResultUnaryOperator(pattern, checkResultListener));
    }

    public CustomTextFormatter(OnChangeListener onChangeListener) {
        super(new OnChangeUnaryOperator(onChangeListener));
    }

    public CustomTextFormatter(Pattern pattern) {
        super(new PatternUnaryOperator(pattern));
    }

    public CustomTextFormatter(UnaryOperator<Change> filter) {
        super(filter);
    }

    public CustomTextFormatter(StringConverter<String> valueConverter, String defaultValue, UnaryOperator<Change> filter) {
        super(valueConverter, defaultValue, filter);
    }

    public CustomTextFormatter(StringConverter<String> valueConverter, String defaultValue) {
        super(valueConverter, defaultValue);
    }

    public CustomTextFormatter(StringConverter<String> valueConverter) {
        super(valueConverter);
    }

    public static class CheckUnaryOperator implements UnaryOperator<Change> {
        private final Pattern pattern;
        private final CheckResultListener checkResultListener;

        public CheckUnaryOperator(Pattern pattern, CheckResultListener checkResultListener) {
            this.pattern = pattern;
            this.checkResultListener = checkResultListener;
        }

        @Override
        public Change apply(Change change) {
            String text = change.getControlNewText();
            if (this.pattern != null && this.checkResultListener != null) {
                this.checkResultListener.onCheckResult(Validator.isMatchRegex(this.pattern, text), text);
            }
            return change;
        }
    }

    public static class CheckResultUnaryOperator implements UnaryOperator<Change> {
        private final Pattern pattern;
        private final CheckResultListener checkResultListener;

        public CheckResultUnaryOperator(Pattern pattern, CheckResultListener checkResultListener) {
            this.pattern = pattern;
            this.checkResultListener = checkResultListener;
        }

        @Override
        public Change apply(Change change) {
            String text = change.getControlNewText();
            if (this.pattern != null && this.checkResultListener != null) {
                this.checkResultListener.onCheckResult(Validator.isMatchRegex(this.pattern, text), text);
            }
            return change;
        }
    }

    public static class OnChangeUnaryOperator implements UnaryOperator<Change> {
        private final OnChangeListener onChangeListener;

        public OnChangeUnaryOperator(OnChangeListener onChangeListener) {
            this.onChangeListener = onChangeListener;
        }

        @Override
        public Change apply(Change change) {
            if (change.getText().isEmpty()) {
                return change;
            }
            if (onChangeListener.onChange(change)) {
                return change;
            }
            return null;
        }
    }

    public static class PatternUnaryOperator implements UnaryOperator<Change> {
        private final Pattern pattern;

        public PatternUnaryOperator(Pattern pattern) {
            this.pattern = pattern;
        }

        @Override
        public Change apply(Change change) {
            if (change.getText().isEmpty()) {
                return change;
            }
            if (Validator.isMatchRegex(pattern, change.getControlNewText())) {
                return change;
            }
            return null;
        }
    }

    public interface CheckResultListener {
        void onCheckResult(boolean pass, String text);
    }

    public interface OnChangeListener {
        boolean onChange(Change change);
    }
}
